package com.authine.cloudpivot.ext.service.impl;

import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.data.support.PageImpl;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.constants.TaxRate;
import com.authine.cloudpivot.ext.domain.Entity.financial.BillEntity;
import com.authine.cloudpivot.ext.domain.Entity.order.*;
import com.authine.cloudpivot.ext.domain.Entity.personalcenter.MemberDeliverAddressEntity;
import com.authine.cloudpivot.ext.domain.Entity.sourcingcenter.InquiryEntity;
import com.authine.cloudpivot.ext.domain.Entity.sourcingcenter.InquiryGoodsEntity;
import com.authine.cloudpivot.ext.domain.Entity.sourcingcenter.QuotationGoodsEntity;
import com.authine.cloudpivot.ext.domain.vo.CartOrderVO;
import com.authine.cloudpivot.ext.domain.vo.order.OrderCustomerVO;
import com.authine.cloudpivot.ext.domain.vo.order.OrderVendorGoodsVO;
import com.authine.cloudpivot.ext.domain.vo.order.OrderVendorVO;
import com.authine.cloudpivot.ext.dto.GatewayResponse;
import com.authine.cloudpivot.ext.dto.HttpClientBO;
import com.authine.cloudpivot.ext.dto.order.StockBillMaterialDto;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.entity.goods.CartEntity;
import com.authine.cloudpivot.ext.entity.goods.GoodsEntity;
import com.authine.cloudpivot.ext.entity.goods.GoodsFullEntity;
import com.authine.cloudpivot.ext.entity.goods.GoodsPurchaseEntity;
import com.authine.cloudpivot.ext.enums.CartSrcEnum;
import com.authine.cloudpivot.ext.enums.commoditymaterials.GoodsPurchaseTypeEnum;
import com.authine.cloudpivot.ext.enums.demandpool.DemandGoodsStatusEnum;
import com.authine.cloudpivot.ext.enums.demandpool.DemandPoolStatusEnum;
import com.authine.cloudpivot.ext.enums.finance.InvoiceStatusEnum;
import com.authine.cloudpivot.ext.enums.finance.PaymentStatusEnum;
import com.authine.cloudpivot.ext.enums.finance.ReconciliationStatusEnum;
import com.authine.cloudpivot.ext.enums.order.*;
import com.authine.cloudpivot.ext.enums.order.transfer.OrderType;
import com.authine.cloudpivot.ext.enums.system.OrganizationAttributeEnum;
import com.authine.cloudpivot.ext.field.OrderCenterTableField;
import com.authine.cloudpivot.ext.fun.ObjectFunction;
import com.authine.cloudpivot.ext.service.GoodsService;
import com.authine.cloudpivot.ext.service.ICartService;
import com.authine.cloudpivot.ext.service.OrderService;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.boQuery.BoQueryUtils;
import com.authine.cloudpivot.ext.utils.convert.BOConvert;
import com.authine.cloudpivot.ext.utils.kingdee.DateUtils;
import com.authine.cloudpivot.ext.utils.system.OrgAttributeUtils;
import com.authine.cloudpivot.ext.utils.system.OrgUtils;
import com.authine.cloudpivot.ext.utils.system.RoleUtils;
import com.authine.cloudpivot.ext.utils.system.UserUtils;
import com.authine.mvp.app.launcher.common.SchemaHelper;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.utils.JsonParseObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.authine.cloudpivot.ext.utils.JdbcTemplateUtils.getTableName;

@Slf4j
public class OrderServiceImpl implements OrderService {


    ICartService iCartService = ICartServiceImpl.getInstance();
    GoodsService goodsService = GoodsServiceImpl.getInstance();
    NamedParameterJdbcTemplate jdbcTemplate = ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);

    private OrderServiceImpl() {
    }

    public static OrderServiceImpl getInstance() {
        return OrderServiceImplBuilder.instance;
    }

    @Override
    public OrderCustomerVO buildCartOrder(List<String> cartIds) throws BizException {

        if (null == cartIds || cartIds.isEmpty()) throw new BizException("请选择购物车商品！");
        //货期购物车信息
        List<CartEntity> cartEntityList = iCartService.listByCartIDs(cartIds);
        List<CartOrderVO> carts = cartEntityList.stream().map(CartOrderVO::entityToVo).collect(Collectors.toList());

        if (carts.isEmpty()) throw new BizException("购物车商品已失效，请重新选择！");

        //获取当前组织和当前登录人
        UserDto currentUser = UserUtils.getCurrentUser();
        OrganizationDto org = OrgUtils.getOrgByUserId();

        //非客户
        if (null == currentUser || !RoleUtils.existByUserIdAndRoleName(currentUser.getId(), PlatformConst.ROLE_CUSTOMER_ADMIN)) {
            throw new BizException("您暂无下单权限！");
        }

        //初始化客户订单
        OrderCustomerVO customerOrder = new OrderCustomerVO();
        //供应商订单
        List<OrderVendorVO> vendorOrders = new ArrayList<>();
        String memId = currentUser.getId();
        //客户账期
        //客户订单商品账期取询价单上的账期, 客户订单账期与供应商订单账期和以前一样取客户组织账期
        //客户订单账期与供应商订单账期字段待删除
        if (null == org.getAccount_id()) {
            throw new BizException("客户账户不存在");
        }
        Integer ap = org.getStatement_cycle() == null ? 0 : org.getStatement_cycle();
        customerOrder.setCartIds(cartIds);
        for (CartOrderVO cart : carts) {

            String goodsId = cart.getGoods_id();
            BigDecimal num = cart.getQuantity();
            GoodsSrcEnum src = GoodsSrcEnum.valueOf(cart.getGoods_src());

            //供应商组织
            OrganizationDto vendorOrg = OrgUtils.getOrgByOrgId(cart.getVendor_organization_id().get(0).getId());

            if (null == vendorOrg) {
                throw new BizException("购物车商品【" + cart.getId() + "】对应的供应商不存在！");
            }

            OrderVendorGoodsVO orderGoods = new OrderVendorGoodsVO();

            orderGoods.setQuantity(num);
            orderGoods.setGoods_id(goodsId);
            orderGoods.setGoods_src(src.name());
            orderGoods.setClient_order_goods_id("");

            // 商城商品
            if (src == GoodsSrcEnum.Shop) {
                customerOrder.setType(OrderTypeEnum.ShopOrder.name());


                GatewayResponse<List<GoodsFullEntity>> goodsFullEntityRestResponse = goodsService.pageMallGoodsByIds(Collections.singletonList(goodsId), null);

                if (goodsFullEntityRestResponse.getData().isEmpty()) {
                    throw new BizException("购物车商品【" + cart.getName() + "】已下架！");
                }
                GoodsFullEntity goods = goodsFullEntityRestResponse.getData().get(0);

                if (null != goods.getStock() && goods.getStock().compareTo(cart.getQuantity()) < 0) {
                    throw new BizException("购物车商品【" + cart.getName() + "】库存不足！请重新选购");
                }

                //加上运费策略后的含税单价
//                Double actPrice = iShopGoodsService.calculateSkuPrice(goods, coa, null);

//                Double pretaxPrice = BigDecimalUtils.div(actPrice, 1 + goods.getTaxRate(), 2);
                BigDecimal pretaxPrice = goods.getPretax_price();

                //商城商品取客户组织账期
                orderGoods.setCustomer_account_period(String.valueOf(ap));
                orderGoods.setCategory(goods.getCategory());
                orderGoods.setBrand(goods.getBrand());
                orderGoods.setName(goods.getName());
                orderGoods.setModel(goods.getModel());
                orderGoods.setSpec(goods.getSpec());

                orderGoods.setDescription(goods.getDescription());
                orderGoods.setUnit(goods.getUnit());
                orderGoods.setPackage_unit(goods.getPackage_unit());
                orderGoods.setPackage_quantity(goods.getPackage_num());
                orderGoods.setWarranty(goods.getWarranty());
                orderGoods.setDelivery(goods.getStock_delivery());

                orderGoods.setLength(goods.getLength());
                orderGoods.setWidth(goods.getWidth());
                orderGoods.setHeight(goods.getHeight());
                orderGoods.setWeight(goods.getWeight());
                orderGoods.setImages(goods.getImages());

                orderGoods.setFreight_rate(TaxRate.Tax_Rate_0_06);
                orderGoods.setPretax_freight(BigDecimal.ZERO);
                orderGoods.setTax_rate(goods.getTax_rate());
                orderGoods.setPretax_price(pretaxPrice);

            } else if (src == GoodsSrcEnum.EnterpriseMall) {
                //客户企业商城

                customerOrder.setType(OrderTypeEnum.ShopOrder.name());
                PageImpl<GoodsEntity> goodsPage = BoQueryUtils.Builder(ModelConst.T_GOODSES).condition()
                        .eq("id", goodsId)
                        .End()
                        .listBO(GoodsEntity.class);


                if (goodsPage.getTotal() == 0) {
                    throw new BizException("购物车商品【" + cart.getName() + "】已下架！");
                }
                GoodsEntity goods = goodsPage.getContent().get(0);


                BigDecimal pretaxPrice = goods.getAdjust_pretax_price();

                //商城商品取客户组织账期
                orderGoods.setCustomer_account_period(String.valueOf(ap));
                orderGoods.setCategory(goods.getCategory());
                orderGoods.setBrand(goods.getBrand());
                orderGoods.setName(goods.getName());
                orderGoods.setModel(goods.getModel());
                orderGoods.setSpec(goods.getSpec());

                orderGoods.setDescription(goods.getDescription());
                orderGoods.setUnit(goods.getUnit());
                orderGoods.setPackage_unit(goods.getPackage_unit());
                orderGoods.setPackage_quantity(goods.getPackage_num());
                orderGoods.setWarranty(goods.getWarranty());
                orderGoods.setDelivery(goods.getDelivery());

                orderGoods.setLength(goods.getLength());
                orderGoods.setWidth(goods.getWidth());
                orderGoods.setHeight(goods.getHeight());
                orderGoods.setWeight(goods.getWeight());
                orderGoods.setImages(goods.getImages());

                orderGoods.setFreight_rate(BigDecimal.ZERO);
                orderGoods.setPretax_freight(BigDecimal.ZERO);
                orderGoods.setTax_rate(goods.getTax_rate());
                orderGoods.setPretax_price(pretaxPrice);
            } else if (src == GoodsSrcEnum.SourcingSingle || src == GoodsSrcEnum.SourcingLoop) {
                PageImpl<GoodsPurchaseEntity> goodsPage = BoQueryUtils.Builder(ModelConst.T_GOODS_PURCHASE).condition()
                        .eq("id", cart.getGoods_id())
                        .End().listBO(GoodsPurchaseEntity.class);
                if (goodsPage.getTotal() == 0) {
                    throw new BizException("购物车商品【" + cart.getId() + "】对应的采购目录商品不存在！");
                }
                GoodsPurchaseEntity goods = goodsPage.getContent().get(0);

                if (!goods.getEnabled()) {
                    throw new BizException("购物车商品【" + cart.getId() + "】对应的采购目录商品已不可采购，请重新选购！");
                }
                Date expire = DateUtils.strToDateDayTime(goods.getExpire());
                if (expire.getTime() < System.currentTimeMillis()) {
                    throw new BizException("购物车商品【" + cart.getId() + "】对应的采购目录商品已过期，请重新询价！");
                }

                if (null == goods.getQuotation_goods_id()) {
                    throw new BizException("购物车商品【" + cart.getId() + "】对应的报价商品不存在！");
                }

                PageImpl<InquiryEntity> iePage = BoQueryUtils.Builder(ModelConst.T_INQUIRY_GOODS).condition()
                        .eq("id", goods.getInquiry_id())
                        .rpc(AppConst.SOURCING_CENTER).listBO(InquiryEntity.class);

                if (iePage.getTotal() == 0) {
                    throw new BizException("未获取到询价单!");
                }

                InquiryEntity ie = iePage.getContent().get(0);
                //循环采购不限制采购权限（子组织也能购买父组织的商品）,判断权限是否符合
                if (!inquiryPermiss(ie, src, currentUser.getId())) {
                    throw new BizException("查看报价商品失败：询价商品不在可操作权限内");
                }

                PageImpl<QuotationGoodsEntity> qgPage = BoQueryUtils.Builder(ModelConst.T_QUOTATION_GOODS).condition()
                        .eq("id", goods.getQuotation_goods_id())
                        .rpc(AppConst.SOURCING_CENTER).listBO(QuotationGoodsEntity.class);

                if (qgPage.getTotal() == 0)
                    throw new BizException("未获取到购物车商品【" + cart.getId() + "】对应的报价商品，暂无采购权限!");

                QuotationGoodsEntity qg = qgPage.getContent().get(0);

                //询价商品
                PageImpl<InquiryGoodsEntity> igPage = BoQueryUtils.Builder(ModelConst.T_INQUIRY_GOODS).condition()
                        .eq("id", goods.getInquiry_goods_id())
                        .rpc(AppConst.SOURCING_CENTER).listBO(InquiryGoodsEntity.class);

                if (igPage.getTotal() == 0) {
                    throw new BizException("未获取到询价商品!");
                }
                InquiryGoodsEntity ig = igPage.getContent().get(0);


                //订单商品关联其他模块的信息
                try {
                    //订单关系记录
                    OrderGoodsRelationEntity or = new OrderGoodsRelationEntity();
                    or.setInquiry_member_id(ie.getMember_id());
                    or.setInquiry_member_name(ie.getMember_name());
                    or.setInquiry_id(ie.getId());
                    or.setDemand_department_name(ig.getDemand_department().get(0).getName());
                    or.setVirtual_quoter_id(qg.getPlatform_quotation_id());
                    //关联业务部门和业务人员
                    String businessMemberId = org.getBusiness_member_id().get(0).getId();
                    UserDto businessMember = null;
                    if (businessMemberId != null) {
                        businessMember = UserUtils.getUserByUserId(businessMemberId);
                    }
                    if (null != businessMember && !businessMember.getDepartment_id().isEmpty()) {
                        or.setBusiness_member_id(businessMember.getId());
                        or.setBusiness_department_id(businessMember.getDepartment_id().get(0).getId());
                    }

                    orderGoods.setCost_center_name(null == ie.getCost_center_name() ? "" : ie.getCost_center_name());
                    orderGoods.setDemand_goods_id(ig.getDemand_goods_id());
                    orderGoods.setOrderGoodsRelationEntity(or);
                    SelectorFormat selectorFormat = Utils.toSelectorFormat(ie.getMember_id());
                    SelectorFormat demand = Utils.toSelectorFormat(goods.getDemand_dept_id());

                    orderGoods.setDemand_department_name(demand != null ? demand.getName() : "");
                    orderGoods.setInquiry_id(ie.getId());
                    orderGoods.setInquiry_member_name(selectorFormat != null ? selectorFormat.getName() : "");
                } catch (Exception e) {
                    log.error("\n异常信息: {}\n发生在: {}", e.getMessage(), e);
                }


                // 订单商品账期取询价单的账期
                orderGoods.setCustomer_account_period(ie.getAccount_period());
                orderGoods.setCategory(null == goods.getCatalog() ? "" : goods.getCatalog());
                orderGoods.setBrand(goods.getBrand());
                orderGoods.setName(goods.getName());
                orderGoods.setModel(goods.getModel());
                orderGoods.setSpec(goods.getSpec());
                orderGoods.setSku(null == goods.getCustomer_sku() ? "" : goods.getCustomer_sku());
                orderGoods.setBar_code(null == goods.getVendor_bar_code() ? "" : goods.getVendor_bar_code());
                orderGoods.setGolden_tax(null == goods.getGolden_tax() ? "" : goods.getGolden_tax());
                orderGoods.setUnspsc(null == goods.getUnspsc() ? "" : goods.getUnspsc());
                orderGoods.setImages(null == goods.getImages() ? Collections.EMPTY_LIST : goods.getImages());
                orderGoods.setDescription(null == goods.getDescription() ? "" : goods.getDescription());
                orderGoods.setUnit(goods.getUnit());
                orderGoods.setPackage_unit(goods.getPackage_unit());
                orderGoods.setPackage_quantity(goods.getPackage_num());
                orderGoods.setDelivery(goods.getDelivery().toPlainString());
                orderGoods.setClarify_tips(null == goods.getClarify_tips() ? "" : goods.getClarify_tips());

                orderGoods.setFreight_rate(goods.getTax_rate_freight());
                orderGoods.setPretax_freight(goods.getPretax_freight());
                orderGoods.setTax_rate(goods.getTax_rate());
                orderGoods.setPretax_price(goods.getPretax_price());
            } else {
                throw new BizException("购物车商品来源错误");
            }
            boolean existVendor = false;

            //判断是否有重复商品
            for (OrderVendorVO vendorOrder : vendorOrders) {
                if (cart.getVendor_organization_id().get(0).getId().equals(vendorOrder.getOrganization_id().get(0).getId())) {
                    if (null == vendorOrder.getGoodsList())
                        vendorOrder.setGoodsList(new ArrayList<>());
                    for (OrderVendorGoodsVO og : vendorOrder.getGoodsList()) {
                        if (cart.getGoods_src().equals(og.getGoods_src()) && cart.getGoods_id().equals(og.getGoods_id()))
                            throw new BizException("购物车存在重复商品,请删除重复商品后重试！");
                    }
                    vendorOrder.getGoodsList().add(orderGoods);
                    vendorOrder.setOrganization_name(org.getName());

                    existVendor = true;
                    break;
                }
            }

            if (!existVendor) {

                OrderVendorVO vo = new OrderVendorVO();
                vo.setOrganization_id(cart.getVendor_organization_id());
                vo.setOrder_vendor_status(OrderVendorStatusEnum.UpcomingPayment.name());
                vo.setAccountPeriod(ap);
                vo.setPlace_order_time(null);
                vo.setOrganization_name(org.getName());

                vo.setGoodsList(new ArrayList<>());
                vo.getGoodsList().add(orderGoods);

                vendorOrders.add(vo);

            }


        }
        //客户订单账期只做记录, 取客户组织账期
        customerOrder.setAccountPeriod(ap);
        customerOrder.setOrderVendorVO(vendorOrders);

        return customerOrder;
    }


    @Override
    public SingleResponse submitOrder(final Map<String, Object> orderCustomer) {
        //供应商订单
        List<Map<String, Object>> orderVendorList = (List<Map<String, Object>>) orderCustomer.get("vendorOrders");

        if (null == orderVendorList || orderVendorList.isEmpty()) {
            return SingleResponse.buildFailure("-1", "订单数据错误");
        }
        //企业采购目录 ids
        List<String> goodsIds = new ArrayList<>();
        //商品来源
        StringBuilder goodsSrc = new StringBuilder("");

        //需求商品ids
        List<String> demandIds = new ArrayList<>();
        //订单关系
        List<Map<String, Object>> relationList = new ArrayList<>();
        orderCustomer.put("relationList", relationList);

        //客户订单商品
        final List<Map<String, Object>> custGoodsList = new ArrayList<>();

        //获取商品来源状态
        if (!CollectionUtils.isEmpty(orderVendorList)) {
            List<Map<String, Object>> orderGoodsList = (List<Map<String, Object>>) orderVendorList.get(0).get("orderGoodsList");
            if (!CollectionUtils.isEmpty(orderGoodsList)) {
                goodsSrc.append(GoodsSrcEnum.switchNew(Integer.valueOf(orderGoodsList.get(0).get("goods_src").toString())).name());;

            }
        }

        //todo 1客户订单、供应商订单、客户订单商品和供应商订单商品状态为未付款，如果为VMI订单（寄售下单），则订单状态为已完成
        if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
            orderCustomer.put("order_customer_status", OrderCustomerStatusEnum.Done.name());
        } else {
            orderCustomer.put("order_customer_status", OrderCustomerStatusEnum.UpcomingPayment.name());
        }

        BoResultFormat.initSys(RequestContext.getCorpLoginId(), orderCustomer);
        SelectorFormat customer_id = JSON.parseObject(JSON.toJSONString(orderCustomer.get("customer_id")), SelectorFormat.class);

        orderCustomer.put("custGoodsList", custGoodsList);

        orderVendorList.forEach(a -> {
            //todo1
            if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
                a.put("order_vendor_status", OrderVendorStatusEnum.Done.name());
            } else {
                a.put("order_vendor_status", OrderVendorStatusEnum.UpcomingPayment.name());
            }
            SelectorFormat vendor_id = Objects.isNull(a.get("vendor_id"))?null:JSON.parseObject(JSON.toJSONString(a.get("vendor_id")), SelectorFormat.class);
            a.put("organization_id", vendor_id);
            a.put("organization_name", vendor_id.getName());
            a.put("order_customer_id", orderCustomer.get("id"));
            a.put("erp_po", orderCustomer.get("erp_po"));
            a.put("after_sale", "未售后");
            BoResultFormat.initSys(RequestContext.getCorpLoginId(), a);

            //客户订单商品和供应商订单商品来源类型是 单次寻源 | 多次寻源,取源商品账期；客户订单商品和供应商订单商品来源类型是 代购 | VMI | 市场,取结算账户账期
            Integer accountPeriod = Integer.valueOf(a.get("account_period").toString());

            ((List<Map<String, Object>>) a.get("orderGoodsList")).forEach(b -> {
                //todo1
                if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
                    b.put("order_customer_goods_status", OrderGoodsStatusEnum.Done.name());
                    b.put("order_vendor_goods_status", OrderGoodsStatusEnum.Done.name());
                } else {
                    b.put("order_customer_goods_status", OrderGoodsStatusEnum.UpcomingPayment.name());
                    b.put("order_vendor_goods_status", OrderGoodsStatusEnum.UpcomingPayment.name());
                }
                //需求池id是否存在
                if (!Objects.isNull(b.get("demand_goods_id"))) {
                    demandIds.add((String) b.get("demand_goods_id"));
                }


                //企业采购目录ids
                goodsIds.add((String) b.get("goods_id"));

//                if (goodsSrc.length() == 0) {
//                    goodsSrc.append(b.get("goods_src"));
//                }

                //订单关系表
                Map<String, Object> relation = null == b.get("relation_id") ? new HashMap<>() : (Map<String, Object>) b.get("relation_id");
                BoResultFormat.initSys(RequestContext.getCorpLoginId(), relation);

                relation.put("delivery_requirements", b.get("delivery_requirements"));

                relationList.add(relation);

                b.put("relation_id", relation.get("id"));
                BoResultFormat.initSys(vendor_id.getId(), b);

                b.put("order_customer_id", orderCustomer.get("id"));
                b.put("order_vendor_id", a.get("id"));

                b.put("customer_organization_id", customer_id);
                b.put("customer_organization_name", null == customer_id ? null : customer_id.getName());
                b.put("vendor_organization_id", vendor_id);
                b.put("vendor_organization_name", null == vendor_id ? null : vendor_id.getName());
                String images = "[]";
                if(!Objects.isNull(b.get("images"))){
                    images = b.get("images") instanceof String ? (String) b.get("images") : JSON.toJSONString(b.get("images"));
                }
                b.put("images",  images);
                b.put("erp_po", orderCustomer.get("erp_po"));
                //数量
                b.put("quantity", b.get("num"));
                //初始化数量
                //已发货数量
                b.put("quantity_shipped", 0.0);
                //已收货数量
                b.put("quantity_received", 0.0);
                //已退未发数量
                b.put("quantity_return_not_shipped", 0.0);
                //已退已发数量
                b.put("quantity_return_shipped", 0.0);
                //仅退收货数量
                b.put("returned_num", 0.0);
                //退的收货部分的数量
                b.put("return_received_num", 0.0);
                //退给平台的收货部分的数量
                b.put("return_pm_received_num", 0.0);
                //数量/单位
                if (!Objects.isNull(b.get("quantity")) && !Objects.isNull(b.get("unit"))) {
                    b.put("quantity_unit", b.get("quantity") + "/" + b.get("unit"));
                }
                //包装数量/单位
                if (!Objects.isNull(b.get("package_quantity")) && !Objects.isNull(b.get("unit"))) {
                    b.put("package_quantity_unit", b.get("package_quantity") + "/" + b.get("unit"));
                }
                //标记信息
//                Map<String, Object> quotationGoods = getQuotationGoods((String) b.get("goods_id"));
//                b.put("remark_message", CollectionUtils.isEmpty(quotationGoods) ?
//                        null : quotationGoods.get("remark_message"));

                //4如果是寻源过来的商品需要从询价单上的账期赋值到订单商品的客户账期字段（customer_account_period）
                b.put("customer_account_period", accountPeriod);
                b.put("vendor_account_period", accountPeriod);
                //商品来源
                b.put("goods_src", GoodsSrcEnum.switchNew(Integer.valueOf(b.get("goods_src").toString())).name());

                //todo1;todo2
                Map<String, Object> custOrderGoods = MapBuilder.create(new HashMap<String, Object>()).putAll(b).build();


                BoResultFormat.initSys(RequestContext.getCorpLoginId(), custOrderGoods);
                custOrderGoods.put("id", SchemaHelper.getId());

                custGoodsList.add(custOrderGoods);

            });
        });

        //done  2由于页面显示的时候是面对客户所以只构建了客户订单商品，后台需要copy客户订单商品到供应商订单商品，除了商品ID不同，目前客户订单商品和供应商订单商品一致

        //todo 3这里需要重复获取企业采购目录商品的信息验证商品信息过期时间没有过期
        Integer expireCount = JdbcTemplateUtils.builder(ModelConst.T_GOODS_PURCHASE)
                .selectField(" count(1) as count  ")
                .in("id", goodsIds)
                .lt("expire", new Date())
                .queryForObject(Integer.class);

        if (expireCount > 0) {
            return SingleResponse.buildFailure("-1", "商品已过期");
        }

        //todo 5持久化客户订单、供应商订单、客户订单商品、供应商订单商品、订单商品关系表(t_order_goods_relation)
        if (null == orderCustomer.get("type")) {
            orderCustomer.put("type", OrderTypeEnum.PurchaseOrder.name());
        } else if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
            orderCustomer.put("type", OrderTypeEnum.VmiOrder.name());
        }

        orderCustomer.put("organization_id", customer_id);
        orderCustomer.put("organization_name", !Objects.isNull(customer_id) ? customer_id.getName() : null);
        orderCustomer.put("place_order_user_id", Utils.createSelecorFormat(RequestContext.getCorpLoginId(), RequestContext.getLoginRealName(), 3));
        orderCustomer.put("place_order_fullname", RequestContext.getLoginRealName());
        orderCustomer.put("after_sale", "未售后");
        //TODO 测试默认开始,等7供应商对应流程做好，判断为对应订单，再将enabled=false
        orderCustomer.put("enabled", true);

        //创建订单
        saveOrder(orderCustomer);

        //订单-》转采
        toTransferOrder(orderCustomer);

        //todo 6如果开启了付款审批，则不做任何操作，否则需要调用订单付款接口，详见订单付款接口

        //todo 7如果是振德组织需要推送给振德系统下单数据，这里是同步的，因为要求他们那下单成功我们这才能成功，他们那下单失败我们这也要失败

        //todo 8如果是vmi订单，需要系统自动调用发货和收货，因为vmi这是生成一个完整的已完成订单，订单并不需要操作订单的流程
        //  --调用 vmi 自动发货和收货

        //done 9
        // --1. 如果当前下单不是VMI类型，需要从客户订单中取出购物车ID，调用删除购物车方法（这里目前是异步，所以如果订单失败了，需要回滚该数据）
        boolean isNotVmi = !GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString());
        List<Map<String, Object>> purchaseList = null;
        if (isNotVmi) {
            List<String> cart_id = (List<String>) orderCustomer.get("cart_id");

            if (cart_id != null && cart_id.size() > 0) {
                //获取采购清单信息
                purchaseList = JdbcTemplateUtils.builder(ModelConst.T_CART)
                        .selectField(" goods_id as id,quantity as num")
                        .in("id", cart_id)
                        .in("goods_src", Arrays.asList(CartSrcEnum.SINGLE.id, CartSrcEnum.LOOP.id))
                        .queryForList();

                //修改清单为已删除
                JdbcTemplateUtils.builder(ModelConst.T_CART)
                        .putFieldAndVal("deleted", 1)
                        .in("id", cart_id)
                        .update();
            }
        }

        //done 10
        // --2. 如果不是vmi订单，并且是企业采购目录商品下单，需要回写企业采购目录数据，这里属于商品模块，我先写到此处，逻辑是：
        // -- 根据下单成功后的购物车ID获取企业采购目录商品（t_goods_purchase）;
        // -- 如果商品类型为单次（t_goods_purchase.type=SINGLE）时，修改商品字段是否可用为不可用（t_goods_purchase.enabled=false），并且已买数量等于下单数量，也就是加入购物车数量（t_goods_purchase.bought=t_cart.num）
        // -- 如果商品类型为多次时（t_goods_purchase.type=LOOP）,修改商品已买数量为累加（t_goods_purchase.bought+t_cart.num）,修改Last时间为当前时间

        if (purchaseList != null && purchaseList.size() > 0) {
            Map<String, Integer> purchaseMap = purchaseList.stream().collect(Collectors.groupingBy(a -> MapUtils.getString(a, "id"), Collectors.summingInt(a -> MapUtils.getIntValue(a, "num"))));

//            Map<String, Object> purchaseMap = purchaseList.stream().collect(Collectors.toMap(a -> (String) a.get("id"), a -> a.get("num"), (k1, k2) -> k1));

            List<Map<String, Object>> updateList = JdbcTemplateUtils.builder(ModelConst.T_GOODS_PURCHASE)
                    .selectField(" id,bought,type")
                    .in("id", purchaseMap.keySet().stream().collect(Collectors.toList()))
                    .queryForList();

            updateList.forEach(a -> {
                GoodsPurchaseTypeEnum goodsType = GoodsPurchaseTypeEnum.get(MapUtils.getInteger(a, "type"));
                if (GoodsPurchaseTypeEnum.SINGLE == goodsType) {
                    a.put("enabled", 0);
                    //采购数量
                    Integer num = purchaseMap.get((String) a.get("id"));
                    a.put("bought", num);
                } else if (GoodsPurchaseTypeEnum.LOOP == goodsType) {
                    //采购数量
                    Integer num = purchaseMap.get((String) a.get("id"));
                    int bought = MapUtils.getIntValue(a, "bought");
                    a.put("bought", bought + num);
                }
                JdbcTemplateUtils.builder(ModelConst.T_GOODS_PURCHASE)
                        .putFieldAndVal(a)
                        .eq("id", a.get("id"))
                        .update();
            });

        }

        //DONE 11如果商品信息中有需求商品ID（demand_goods_id）,需要调用更改需求商品状态和需求单状态，该修改方法请寻源需求模块提供
        //设置需求池商品matching为true,状态为已转订单
        if (!demandIds.isEmpty()) {

            updateDemandGoods(demandIds);
        }


        return SingleResponse.of(true);
    }


    private void updateDemandGoods(List<String> demandIds) {
        demandIds.forEach(a -> {
            String demand_pool_id = JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_GOODS)
                    .selectField(" demand_pool_id ")
                    .eq("id", a)
                    .queryForObject(String.class);

            if (StringUtils.isNotBlank(demand_pool_id)) {
                //把当前需求商品的状态改为  已转订单
                JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_GOODS)
                        .putFieldAndVal("demand_goods_status", DemandGoodsStatusEnum.DEMAND_GOODS_3_ORDER.getCode())
                        .eq("id", a)
                        .update();


                // 通过需求池id 获取 需求商品的商品状态
                List<String> demand_goods_status = JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_GOODS)
                        .selectField(" demand_goods_status ")
                        .eq("demand_pool_id", demand_pool_id)
                        .queryForList(String.class);

                String status = DemandPoolStatusEnum.DEMAND_6_EXECUTE_ALL.getCode();
                if (demand_goods_status != null) {
                    for (String b : demand_goods_status) {
                        if (!b.equals(DemandGoodsStatusEnum.DEMAND_GOODS_3_ORDER) && !b.equals(DemandGoodsStatusEnum.DEMAND_GOODS_2_INQUIRY)) {

                            // 需求池的状态
                            status = DemandPoolStatusEnum.DEMAND_5_EXECUTE_PART.getCode();
                            break;
                        }
                    }
                }

                //执行修改
                JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_POOL)
                        .putFieldAndVal("demand_pool_status", status)
                        .eq("id", demand_pool_id)
                        .update();
            }
        });


    }


    @Override
    public SingleResponse orderBeforCondition(final Map<String, Object> data) {

        //todo  判断 只有客户角色才可创建订单!
        String corpLoginId = RequestContext.getCorpLoginId();

        //todo  当前组织必须存在客户管理员角色
        //todo  如果开启了超期未开票属性，需要根据当前组织调用财务是否存在产生收货账单后超过三十天没有申请开票，如果有则不通过
        //todo 当前组织必须存在结算组织
        //todo 获取结算组织，并且结算组织的账户不能为空（t_organization.account_id notnull），结算组织的账期不能为空并且不能小于0（t_organization.statement_cycle notnull &&>=0）
        //todo 如果商品来源类型为单次时，需要验证当前下单人所属的权限（userAapi.listSubMemberIds()）必须包含下单商品对应询价人用户ID，但是如果当前用户拥有权限XXX（名称暂未定义，做好后会补充）则此验证跳过（ps 这里的验证逻辑感觉跨越所属权限了，因为下单商品来源有好几种，这种商品的验证交给不同种类的商品接口内部去处理即可）


        return SingleResponse.of(true);
    }

    private void saveOrder(final Map<String, Object> orderCustomer) {


        //客户订单
        Map<String, Object> cust = MapBuilder.create(new HashMap<String, Object>()).putAll(orderCustomer).build();


        //客户订单商品
        List<Map<String, Object>> custGoodsList = (List<Map<String, Object>>) cust.remove("custGoodsList");

        //供应商订单
        List<Map<String, Object>> orderVendorList = (List<Map<String, Object>>) cust.remove("vendorOrders");
        //供应商订单商品表
        List<Map<String, Object>> vendorGoodsList = new ArrayList<>();
        orderVendorList.forEach(a -> {
            List<Map<String, Object>> orderGoodsList = (List<Map<String, Object>>) a.remove("orderGoodsList");
            vendorGoodsList.addAll(orderGoodsList);
        });


        //订单关系表
        List<Map<String, Object>> relationList = (List<Map<String, Object>>) cust.remove("relationList");


        log.info("===============\n");
        log.info("===============客户订单=\n{}", cust);
        log.info("===============\n");
        log.info("===============客户订单商品=\n{}", custGoodsList);
        log.info("===============\n");
        log.info("===============供应商订单=\n{}", orderVendorList);
        log.info("===============\n");
        log.info("===============供应商订单商品=\n{}", vendorGoodsList);
        log.info("===============\n");
        log.info("===============订单关系表=\n{}", relationList);

        List<String> split = new ArrayList<>();
        split.addAll(cust.keySet());
        split.removeAll(Arrays.asList(OrderCenterTableField.t_order_customer.split(",")));
        split.forEach(b -> cust.remove(b));

        // 把 SelectorFormat Map List 序列化
        ObjectFunction selectorConvert = (a) -> {
            Map.Entry<String, Object> entry = (Map.Entry<String, Object>) a;

            if (entry.getValue() == null) {
                return entry;
            }
            if (entry.getValue() instanceof SelectorFormat
                    || entry.getValue() instanceof List
                    || entry.getValue() instanceof Map) {
                entry.setValue(JSON.toJSONString(entry.getValue()));
            }


            return entry;
        };


        cust.entrySet().forEach(selectorConvert::convert);

        //客户订单save
        JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER)
                .putFieldAndVal(cust)
                .insert();


        //客户订单商品save
        split.clear();
        custGoodsList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_customer_goods.split(",")));
            }

            split.forEach(b -> a.remove(b));

            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS)
                    .putFieldAndVal(a)
                    .insert();
        });


        //供应商订单表save
        split.clear();
        orderVendorList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_vendor.split(",")));
            }
            split.forEach(b -> a.remove(b));

            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR)
                    .putFieldAndVal(a)
                    .insert();
        });


        //供应商商品订单订单表save
        split.clear();
        vendorGoodsList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_vendor_goods.split(",")));
            }
            split.forEach(b -> a.remove(b));
            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR_GOODS)
                    .putFieldAndVal(a)
                    .insert();
        });

        //订单关系表save
        split.clear();
        relationList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_goods_relation.split(",")));
            }
            split.forEach(b -> a.remove(b));
            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION)
                    .putFieldAndVal(a)
                    .insert();
        });
    }

    /**
     * 根据消耗创建订单(订单中心-寄售消耗统计-消耗待结算明细-生成订单)
     *
     * @param idList
     * @return
     */
    @Override
    public SingleResponse buildVmiOrder(List<String> idList) {
        if (null == idList || idList.isEmpty()) throw new RuntimeException("明细id为空!");
        List<Map<String, Object>> sbmeList = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_STOCK_BILL_MATERIAL)
                .selectField("*").in("id", idList).queryForList();
        if (null == sbmeList || sbmeList.isEmpty()) throw new RuntimeException("明细单据不存在!");

        Map<String, Object> customerOrder = new HashMap<>();
        List<Map<String, Object>> vendorOrders = new ArrayList<>();

        List<String> idsList = new ArrayList<>();

        List<StockBillMaterialDto> stockBillMaterialVOS = new ArrayList<>();
        for (Map<String, Object> sme : sbmeList) {

            //非客户承担不结算
            if (!sme.get("bear_type").equals(BearTypeEnum.CUSTOMER_BEAR.name())) {
                continue;
            }

            //非盘亏、非领用、非退料不结算
            if (!sme.get("type").equals(StockBillMaterialTypeEnum.CHECK_LOSS.name()) && !sme.get("type").equals(StockBillMaterialTypeEnum.USE.name()) && !sme.get("type").equals(StockBillMaterialTypeEnum.RETURN.name())) {
                continue;
            }

            //参与结算的记录
            idsList.add((String) sme.get("id"));

            if (null == stockBillMaterialVOS || stockBillMaterialVOS.isEmpty()) {
                stockBillMaterialVOS.add(new StockBillMaterialDto(JSON.parseObject((String) sme.get("vendor_id"), SelectorFormat.class), (String) sme.get("goods_id"), BigDecimalUtils.isNull(sme.get("num"))));
            } else {
                Boolean flag = true;
                for (StockBillMaterialDto sbmVOS : stockBillMaterialVOS) {
                    if (sbmVOS.getGoodsId().equals(sme.get("goods_id"))) {
                        sbmVOS.setNum(BigDecimalUtils.add(sbmVOS.getNum(), BigDecimalUtils.isNull(sme.get("num"))));
                        flag = false;
                    }
                }
                if (flag) {
                    stockBillMaterialVOS.add(new StockBillMaterialDto(JSON.parseObject((String) sme.get("vendor_id"), SelectorFormat.class), (String) sme.get("goods_id"), BigDecimalUtils.isNull(sme.get("num"))));
                }
            }
        }

        //整理消耗数据，订单处理完后，通过此ids改变原单据状态
        String ids = org.apache.commons.lang3.StringUtils.join(idsList, ",");
        customerOrder.put("vmi_ids", ids);

        //创建订单
        for (StockBillMaterialDto sme : stockBillMaterialVOS) {

            String goodsId = sme.getGoodsId();
            SelectorFormat vendorId = sme.getVendorId();
            BigDecimal num = sme.getNum();

            Map<String, Object> orderGoods = new HashMap<>();

            Map<String, Object> goods = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODS_PURCHASE)
                    .selectField("*").eq("id", goodsId).queryForMap();
            if (CollectionUtils.isEmpty(goods)) throw new RuntimeException("来源vmi商品不存在！");

            //最大库存量
            Map<String, Object> inquiryGoods = getInquiryGoodsByGoodsId(goodsId);
            String costCenterName = null == inquiryGoods || inquiryGoods.isEmpty() ? null : (String) inquiryGoods.get("cost_center_name");

            orderGoods.put("category", null == goods.get("catalog") ? "" : goods.get("catalog"));
            orderGoods.put("brand", goods.get("brand"));
            orderGoods.put("name", goods.get("name"));
            orderGoods.put("model", goods.get("model"));
            orderGoods.put("spec", goods.get("spec"));
            orderGoods.put("sku", null == goods.get("customer_sku") ? "" : goods.get("customer_sku"));
            orderGoods.put("bar_code", goods.get("vendor_bar_code"));
            orderGoods.put("golden_tax", goods.get("golden_tax"));
            orderGoods.put("unspsc", goods.get("unspsc"));
            orderGoods.put("images", Optional.ofNullable(goods.get("images")).orElse(""));
            orderGoods.put("description", goods.get("description"));
            orderGoods.put("technical", "");
            orderGoods.put("packaging", "");
            orderGoods.put("unit", goods.get("unit"));
            orderGoods.put("package_unit", goods.get("package_unit"));
            orderGoods.put("package_num", goods.get("package_num"));
            orderGoods.put("warranty", "");
            orderGoods.put("delivery", goods.get("delivery"));
            orderGoods.put("length", null);
            orderGoods.put("width", null);
            orderGoods.put("height", null);
            orderGoods.put("weight", null);
            orderGoods.put("cost_center_name", costCenterName);
            orderGoods.put("demand_goods_id", null);

            orderGoods.put("num", num);

            orderGoods.put("tax_rate", goods.get("tax_rate"));
            orderGoods.put("pretax_freight", goods.get("pretax_freight"));
            orderGoods.put("tax_rate_freight", goods.get("tax_rate_freight"));
            orderGoods.put("pretax_price", goods.get("pretax_price"));

            orderGoods.put("order_customer_goods_status", OrderGoodsStatusEnum.UpcomingPayment.name());

            orderGoods.put("goods_id", goodsId);
            orderGoods.put("cart_src", CartSrcEnum.VMI.id);
            orderGoods.put("goods_src", CartSrcEnum.VMI.id);
            orderGoods.put("delivery_time", null);
            orderGoods.put("customer_account_period", 0);
            orderGoods.put("vendor_account_period", 0);
            orderGoods.put("customer_period_time", null);
            orderGoods.put("vendor_period_time", null);
            orderGoods.put("attachment", null);
            orderGoods.put("client_order_goods_id", "");

            orderGoods.put("vendor_organization_id", vendorId);
            orderGoods.put("clarify_tips", null);
            orderGoods.put("cost_center_name", null);
            orderGoods.put("region", null);
            orderGoods.put("company", null);
            orderGoods.put("warehouse", null);
            orderGoods.put("deliveryRequirements", null);
            orderGoods.put("demand_goods_id", null);

            // 计算
            orderGoods.put("tax_payable", ObjectUtil.defaultIfNull(goods.get("pretax_price"), FinancialCalculationUtils.calculateTaxPayableByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("tax_rate")), num)));
            orderGoods.put("tax_payable_freight", ObjectUtil.defaultIfNull(goods.get("pretax_price"), FinancialCalculationUtils.calculatePayableFreightByPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_freight")), BigDecimalUtils.isNull(goods.get("tax_rate_freight")))));
            orderGoods.put("price", FinancialCalculationUtils.calculatePriceByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("tax_rate"))));
            orderGoods.put("freight", FinancialCalculationUtils.calculateFreightByPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_freight")), BigDecimalUtils.isNull(goods.get("tax_rate_freight"))));
            orderGoods.put("pretax_total", FinancialCalculationUtils.calculatePretaxTotalByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), num));
            orderGoods.put("total", FinancialCalculationUtils.calculateTotalByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("tax_rate")), num));
            orderGoods.put("pretax_amount", FinancialCalculationUtils.calculatePretaxAmountByPretaxPriceAndPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("pretax_freight")), num));
            orderGoods.put("amount", FinancialCalculationUtils.calculateAmountByPretaxPriceAndPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("pretax_freight")), BigDecimalUtils.isNull(goods.get("tax_rate")), BigDecimalUtils.isNull(goods.get("tax_rate_freight")), num));

            boolean existVendor = false;
            for (Map<String, Object> vendorOrder : vendorOrders) {
                if (vendorId.equals(vendorOrder.get("vendor_id"))) {
                    List<Map<String, Object>> vendorOrderGoods = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR_GOODS)
                            .selectField("*").eq("order_vendor_id", vendorOrder.get("id")).queryForList();
                    // 计算
                    vendorOrder.put("tax_rate", ObjectUtil.defaultIfNull(vendorOrder.get("tax_rate"), 0.16));
                    vendorOrder.put("tax_rate_freight", ObjectUtil.defaultIfNull(vendorOrder.get("tax_rate_freight"), 0.0));
                    vendorOrder.put("tax_payable", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("tax_payable"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable")).doubleValue()).sum());
                    vendorOrder.put("tax_payable_freight", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("tax_payable_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable_freight")).doubleValue()).sum());
                    vendorOrder.put("pretax_freight", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("pretax_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_freight")).doubleValue()).sum());
                    vendorOrder.put("freight", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("freight")).doubleValue()).sum());
                    vendorOrder.put("pretax_total", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("pretax_total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_total")).doubleValue()).sum());
                    vendorOrder.put("total", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum());
                    vendorOrder.put("pretax_amount", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("pretax_amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_amount")).doubleValue()).sum());
                    vendorOrder.put("amount", vendorOrderGoods.stream().filter(t -> !Objects.isNull(t.get("amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum());

                    vendorOrder.put("memo", "");
                    vendorOrder.put("organization_name", vendorId.getName());

                    vendorOrderGoods.add(orderGoods);
                    vendorOrder.put("orderGoodsList", vendorOrderGoods);
                    existVendor = true;
                    break;
                }
            }

            if (!existVendor) {
                Map<String, Object> vendorOrderEntity = new HashMap<>();
                vendorOrderEntity.put("vendor_id", vendorId);
                vendorOrderEntity.put("organization_name", vendorId.getName());
                vendorOrderEntity.put("order_vendor_status", OrderVendorStatusEnum.UpcomingPayment.name());
                vendorOrderEntity.put("account_period", 0);
                vendorOrderEntity.put("orders_time", null);

                //获取供应商用户信息
                if (null != vendorId) {
                    vendorOrderEntity.put("orders_member", vendorId.getId());
                    vendorOrderEntity.put("member_name", vendorId.getName());
                    vendorOrderEntity.put("user_name", vendorId.getName());
                }
                // 计算
                vendorOrderEntity.put("tax_rate", ObjectUtil.defaultIfNull(vendorOrderEntity.get("tax_rate"), 0.16));
                vendorOrderEntity.put("tax_rate_freight", ObjectUtil.defaultIfNull(vendorOrderEntity.get("tax_rate_freight"), 0.0));
                vendorOrderEntity.put("tax_payable", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("tax_payable"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable")).doubleValue()).sum());
                vendorOrderEntity.put("tax_payable_freight", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("tax_payable_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable_freight")).doubleValue()).sum());
                vendorOrderEntity.put("pretax_freight", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("pretax_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_freight")).doubleValue()).sum());
                vendorOrderEntity.put("freight", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("freight")).doubleValue()).sum());
                vendorOrderEntity.put("pretax_total", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("pretax_total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_total")).doubleValue()).sum());
                vendorOrderEntity.put("total", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum());
                vendorOrderEntity.put("pretax_amount", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("pretax_amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_amount")).doubleValue()).sum());
                vendorOrderEntity.put("amount", Collections.singletonList(orderGoods).stream().filter(t -> !Objects.isNull(t.get("amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum());

                vendorOrderEntity.put("memo", "");

                vendorOrders.add(vendorOrderEntity);
                vendorOrderEntity.put("orderGoodsList", Collections.singletonList(orderGoods));
            }
        }

        // 计算
        customerOrder.put("tax_rate", ObjectUtil.defaultIfNull(customerOrder.get("tax_rate"), 0.16));
        customerOrder.put("tax_rate_freight", ObjectUtil.defaultIfNull(customerOrder.get("tax_rate_freight"), 0.16));
        customerOrder.put("tax_payable", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("tax_payable"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable")).doubleValue()).sum());
        customerOrder.put("tax_payable_freight", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("tax_payable_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable_freight")).doubleValue()).sum());
        customerOrder.put("pretax_freight", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("pretax_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_freight")).doubleValue()).sum());
        customerOrder.put("freight", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("freight")).doubleValue()).sum());
        customerOrder.put("pretax_total", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("pretax_total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_total")).doubleValue()).sum());
        customerOrder.put("total", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum());
        customerOrder.put("pretax_amount", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("pretax_amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_amount")).doubleValue()).sum());
        customerOrder.put("amount", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum());

        customerOrder.put("cart_id", "");
        customerOrder.put("cartIds", idList.size());
        customerOrder.put("erp_po", "");
        //个人收货信息
        List<Map<String, Object>> deliverAddressList = JdbcTemplateUtils.builder(AppConst.PERSONAL_CENTER, ModelConst.T_MEMBER_DELIVER_ADDRESS).selectField("*")
                .eq("default_address", true).eq("member_id -> '$.id'", RequestContext.getCorpLoginId()).queryForList();
        if (!CollectionUtils.isEmpty(deliverAddressList)) {
            Map<String, Object> deliverAddress = deliverAddressList.get(0);
            customerOrder.put("receiver", deliverAddress.get("receiver_name"));
            customerOrder.put("phone", deliverAddress.get("mobile"));
            customerOrder.put("address", deliverAddress.get("area") + " " + deliverAddress.get("address"));
            customerOrder.put("postal", deliverAddress.get("post"));
        } else {
            customerOrder.put("receiver", "");
            customerOrder.put("phone", "");
            customerOrder.put("address", "");
            customerOrder.put("postal", "");
        }
        customerOrder.put("account_period", 0);
        customerOrder.put("customer_id", BoResultFormat.getMainDept(RequestContext.getCorpLoginId()));
        customerOrder.put("vendorOrders", vendorOrders);
        return SingleResponse.of(customerOrder);
    }

    /**
     * 普通订单-》转采订单
     *
     * @param orderCustomer
     * @return
     */
    @Override
    public void toTransferOrder(Map<String, Object> orderCustomer) {
        if (CollectionUtils.isEmpty(orderCustomer)) {
            return;
        }
        //客户订单商品
        List<Map<String, Object>> custGoodsList = (List<Map<String, Object>>) orderCustomer.remove("custGoodsList");
        //供应商订单
        List<Map<String, Object>> orderVendorList = (List<Map<String, Object>>) orderCustomer.remove("vendorOrders");
        //判断是否为虚拟供应商
        List<Map<String, Object>> voList = orderVendorList.stream().filter(t -> isVirtual(Objects.isNull(t.get("organization_id")) ? null : JSON.parseObject((String) t.get("organization_id"), SelectorFormat.class))).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(voList)) {
//            BigDecimal total = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum()), 2);
//            BigDecimal preTotal = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_total")).doubleValue()).sum()), 2);
//            BigDecimal amount = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum()), 2);
//            BigDecimal preAmount = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_amount")).doubleValue()).sum()), 2);

            Map<String, Object> transferOrder = new HashMap<>();
            String platformId = null;
            String platformName = null;
            String orderType = custGoodsList.get(0).get("goods_src").equals(GoodsSrcEnum.Contract) ? OrderType.Contract.name() : OrderType.Purchase.name();
            SelectorFormat memberId = ObjectUtil.defaultIfNull((SelectorFormat) orderCustomer.get("place_order_user_id"), null);
            transferOrder.put("member_id", JSON.toJSONString(memberId));
            transferOrder.put("cloud_order_id", orderCustomer.get("id"));
            transferOrder.put("user_name", ObjectUtil.defaultIfNull(memberId.getName(), null));
            SelectorFormat organizationId = ObjectUtil.defaultIfNull((SelectorFormat) orderCustomer.get("organization_id"), null);
            transferOrder.put("organization_id", JSON.toJSONString(organizationId));
            transferOrder.put("organization_name", ObjectUtil.defaultIfNull(organizationId.getName(), null));
            transferOrder.put("account_period", custGoodsList.get(0).get("customer_account_period"));
            transferOrder.put("tax_rate", orderCustomer.get("tax_rate"));
            transferOrder.put("total", orderCustomer.get("total"));
            transferOrder.put("pre_total", orderCustomer.get("pretax_total"));
            transferOrder.put("amount", orderCustomer.get("amount"));
            transferOrder.put("pre_amount", orderCustomer.get("pretax_amount"));
            transferOrder.put("receiver", orderCustomer.get("receiver"));
            transferOrder.put("phone", orderCustomer.get("phone"));
            transferOrder.put("postal", orderCustomer.get("postal"));
            transferOrder.put("address", orderCustomer.get("address"));
            transferOrder.put("order_type", orderType);
            transferOrder.put("is_contract", StringUtils.isNotBlank(orderType) && orderType.equals(OrderType.Contract.name()) ? true : false);
            transferOrder.put("transfer_order_status", OrderCustomerStatusEnum.UpcomingPayment.name());
            transferOrder.put("erp_po", orderCustomer.get("erp_po"));
            if (null != organizationId) {
                Map<String, Object> organization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION).eq("id", organizationId.getId()).queryForMap();
                if (!CollectionUtils.isEmpty(organization)) {
                    platformId = Objects.isNull(organization.get("platform_id")) ? null : JsonParseObject.parseObject((String) organization.get("platform_id"), SelectorFormat.class).get(0).getId();
                    platformName = CollectionUtils.isEmpty(organization) ? null : (String) organization.get("platform_name");
                    transferOrder.put("platform_id", platformId);
                    transferOrder.put("platform_name", platformName);
                }
            }
            BoResultFormat.initSys(RequestContext.getCorpLoginId(), transferOrder);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_TRANSFER_ORDER).putFieldAndVal(transferOrder).insert();

            for (Map<String, Object> voe : voList) {
                List<Map<String, Object>> orderGoodsList = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS).selectField("*").eq("order_customer_id", voe.get("order_customer_id")).queryForList();
                SelectorFormat vendorId = ObjectUtil.defaultIfNull(JSON.parseObject((String) voe.get("organization_id"), SelectorFormat.class), null);
                for (Map<String, Object> oge : orderGoodsList) {
                    Map<String, Object> transferOrderGoods = MapBuilder.create(new HashMap<String, Object>())
                            //状态转换
                            .put("transfer_order_goods_status", oge.get("order_customer_goods_status"))
                            .put("cloud_order_goods_id", oge.get("id"))
                            .put("vendor_id", JSON.toJSONString(vendorId))
                            .put("vendor_name", ObjectUtil.defaultIfNull(vendorId.getName(), null))
                            .put("category", oge.get("category"))
                            .put("brand", oge.get("brand"))
                            .put("name", oge.get("name"))
                            .put("model", oge.get("model"))
                            .put("spec", oge.get("spec"))
                            .put("sku", oge.get("sku"))
                            .put("memo", oge.get("description"))
                            .put("unit", oge.get("unit"))
                            .put("delivery", oge.get("delivery"))
                            .put("num", oge.get("quantity"))
                            .put("price", oge.get("price"))
                            .put("pre_price", oge.get("pretax_price"))
                            .put("freight", oge.get("freight"))
                            .put("tax_rate", oge.get("tax_rate"))
                            .put("total", oge.get("total"))
                            .put("pre_total", oge.get("pretax_total"))
                            .put("amount", oge.get("amount"))
                            .put("not_purchase", false)
                            .put("pre_amount", oge.get("pretax_amount")).build();
                    //询价商品id
                    if (null != oge.get("relation_id")) {
                        Map<String, Object> orderGoodsRelation = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION).selectField("*")
                                .eq("id", oge.get("relation_id")).queryForMap();
                        if (orderGoodsRelation != null) {
                            transferOrderGoods.put("inquiry_id", orderGoodsRelation.get("inquiry_td"));
                        }
                    }
                    transferOrderGoods.put("remark_message", CollectionUtils.isEmpty(getQuotationGoods((String) oge.get("goods_id")))? null:getQuotationGoods((String) oge.get("goods_id")).get("remark_message"));
                    transferOrderGoods.put("platform_name", platformName);
                    transferOrderGoods.put("order_type", orderType);
                    transferOrderGoods.put("cloud_order_id", orderCustomer.get("id"));
                    transferOrderGoods.put("user_name", ObjectUtil.defaultIfNull(memberId.getName(), null));
                    transferOrderGoods.put("organization_name", ObjectUtil.defaultIfNull(organizationId.getName(), null));
                    BoResultFormat.initSys(RequestContext.getCorpLoginId(), transferOrderGoods);
                    transferOrderGoods.put("transfer_order_id", transferOrder.get("id"));
                    JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_TRANSFER_ORDER_GOODS).putFieldAndVal(transferOrderGoods).insert();
                }
            }
        }
    }

    /**
     * 通过商品ID获取报价商品信息
     *
     * @return
     */
    public Map<String, Object> getQuotationGoods(String goodsId) {
        if(StringUtils.isBlank(goodsId)){
            return null;
        }
        Map<String, Object> quotationGoods = null;
        Map<String, Object> goodsPurchase = JdbcTemplateUtils.builder(ModelConst.T_GOODS_PURCHASE).selectField("*").eq("id", goodsId).queryForMap();
        if (null != goodsPurchase) {
            quotationGoods = JdbcTemplateUtils.builder(AppConst.SOURCING_CENTER, ModelConst.T_QUOTATION_GOODS).selectField("*").eq("id", goodsPurchase.get("quotation_goods_id")).queryForMap();
        }
        return quotationGoods;
    }


    /**
     * 判断当前供应商是否为虚拟供应商
     *
     * @return
     */
    public boolean isVirtual(SelectorFormat dept) {
        if (null == dept) {
            return false;
        }
        Map<String, Object> organization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION)
                .selectField("*").eq("id", dept.getId()).queryForMap();
        if (!CollectionUtils.isEmpty(organization) && organization.get("virtual").toString().equals("1")) {
            return true;
        }
        return false;
    }

    /**
     * 获取询价商品
     *
     * @param goodsId
     * @return
     */
    public Map<String, Object> getInquiryGoodsByGoodsId(String goodsId) {
        if (StringUtils.isBlank(goodsId)) {
            return null;
        }
        //最大库存量
        StringBuilder listSql = new StringBuilder();
        String goodsPurchaseTableName = getTableName(ModelConst.T_GOODS_PURCHASE, AppConst.COMMODITYMATERIALS);
        String quotationGoodsTableName = getTableName(ModelConst.T_QUOTATION_GOODS, AppConst.SOURCING_CENTER);
        String inquiryGoodsTableName = getTableName(ModelConst.T_INQUIRY_GOODS, AppConst.SOURCING_CENTER);
        listSql.append("select ig.* from " + goodsPurchaseTableName + " pg\n" +
                " inner join " + quotationGoodsTableName + " qg on pg.quotation_goods_id = qg.id\n" +
                " inner join " + inquiryGoodsTableName + " ig on qg.inquiry_goods_id = ig.id\n" +
                " where pg.id = '" + goodsId + "' and pg.deleted = '0' and qg.deleted ='0' and ig.deleted ='0'");
        List<Map<String, Object>> results = JdbcTemplateUtils.queryForList(listSql.toString(), new HashMap<>());
        if (CollectionUtils.isEmpty(results)) {
            return null;
        } else {
            return results.get(0);
        }
    }

    @Override
    public OrderCustomerVO builderCustomerOrder(List<String> cartIds) throws BizException {
        Integer aLong = JdbcTemplateUtils.builder(ModelConst.T_CART)
                .selectField(" count(*) as count").in("id", cartIds).queryForObject(Integer.class);
        if (aLong.intValue() != cartIds.size()) {
            throw new BizException("购物车商品不存在, 该商品可能已在订单处理中!");
        }
        OrderCustomerVO customerOrder = buildCartOrder(cartIds);

        List<MemberDeliverAddressEntity> deliverAddressList = listMemberDeliverAddressByMember(RequestContext.getCorpLoginId(), true, null);
        if (null != deliverAddressList && !deliverAddressList.isEmpty()) {
            MemberDeliverAddressEntity deliverAddress = deliverAddressList.get(0);
            customerOrder.setReceiver(deliverAddress.getReceiver_name());
            customerOrder.setPhone(deliverAddress.getMobile());
            customerOrder.setAddress(deliverAddress.getArea_id().getCityName() + " " + deliverAddress.getAddress());
            customerOrder.setPostal(deliverAddress.getPost());
        }
        return customerOrder;
    }

    @Override
    public OrderCustomerVO createOrder(OrderCustomerVO customerOrder) throws Exception {
        UserDto currentUser = UserUtils.getCurrentUser();
        if (null == currentUser) {
            throw new BizException("未获取到登录信息!");
        }
        String memberId = currentUser.getId();
        String clientId = currentUser.getClient_id();
        String orgId = currentUser.getOrganization_id().get(0).getId();
        if (orgId == null) throw new BizException("组织ID为空!");

        OrganizationDto org = OrgUtils.getOrgByOrgId(orgId);

        if (null == org) {
            throw new BizException("用户组织不可用!");
        }

        if (!RoleUtils.existByUserIdAndRoleName(memberId, PlatformConst.ROLE_CUSTOMER_ADMIN)) {
            throw new BizException("只有客户角色才可创建订单!");
        }
        boolean overdue = OrgAttributeUtils.isEnabledAttribute(orgId, OrganizationAttributeEnum.OVERDUE_BUT_NOT_INVOICED);
        if (overdue == true) {
            List<String> orgIds = OrgUtils.getOrgListByOrgId(orgId).stream().map(OrganizationDto::getId).collect(Collectors.toList());

            if (null == orgIds || orgIds.isEmpty()) throw new BizException("获取的ID列表为空");

            StringBuilder sql = new StringBuilder("SELECT bill.direction from i_financialcenter_t_bill bill ")
                    .append("LEFT JOIN i_financialcenter_t_trade trade on bill.trade_id = trade.id ")
                    .append("where  bill.deleted = 0 and   trade.invoice_status =:invoice_status and bill.direction =:direction ");


            Map<String, Object> param = new HashMap<>();
            param.put("invoice_status", "");
            param.put("direction", "");

            List<BillEntity> list = jdbcTemplate.query(sql.toString(), param, BeanPropertyRowMapper.newInstance(BillEntity.class, new BOConvert()));

            // SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            Date delivery = null;
            for (int i = 0; i < list.size(); i++) {
                delivery = DateUtils.strToDateDayTime(list.get(i).getBill_date());
                int day = (int) ((now.getTime() - delivery.getTime()) / (1000 * 3600 * 24));
                if (day > 30)
                    throw new BizException("部分商品已收货超30天，仍未申请开票,请前往申票，否则无法创建订单！");
            }

        }
        if (null == org.getTransaction_organization_id().get(0).getId()) {
            throw new BizException("请联系平台管理员添加客户结算组织!");
        }

        OrganizationDto tranOrg = org;
        if (!org.getId().equals(org.getTransaction_organization_id().get(0).getId())) {
            tranOrg = OrgUtils.getOrgByOrgId(org.getTransaction_organization_id().get(0).getId());

            if (null == tranOrg) {
                throw new BizException("未获取到对应的结算组织!");
            }
        }


        if (null == tranOrg.getAccount_id()) {
            throw new BizException("结算组织账户不能为空，请联系管理员添加结算组织账户!");
        }

        //客户账期
        Integer cap = tranOrg.getStatement_cycle();
        if (null == cap || cap < 0) {
            throw new BizException("请联系平台管理员添加客户账期!");
        }
        //检测客户订单参数
        checkOrder(customerOrder);
        //设置客户订单属性->客户下单客户订单状态为待付款
        customerOrder.setStatus(OrderCustomerStatusEnum.UpcomingPayment.name());

        customerOrder.setAccountPeriod(cap);

        if (null == customerOrder.getType()) {
            customerOrder.setType(OrderTypeEnum.PurchaseOrder.name());
        }

        customerOrder.setPlace_order_user_id(currentUser.createSelectorFormatList());
        customerOrder.setPlace_order_fullname(currentUser.getRoleName());
        customerOrder.setOrganization_name(org.getName());
        customerOrder.setOrganization_id(org.createSelectorFormatList());

        customerOrder.setReconciliationStatus(ReconciliationStatusEnum.UNDO);
        customerOrder.setInvoiceStatus(InvoiceStatusEnum.UNDO);
        customerOrder.setPaymentStatus(PaymentStatusEnum.UNDO);
        // 客户查询被邀请的供应商组织
        List<String> vendorIds = OrgUtils.listVendorByCustomerId(orgId);

        //默认不是代购
        boolean ifContract = false;
        //循环设置供应商订单商品信息
        for (OrderVendorVO vendorOrder : customerOrder.getOrderVendorVO()) {
            //客户下单 ->供应商订单状态为新建
            vendorOrder.setOrder_vendor_status(OrderVendorStatusEnum.UpcomingPayment.name());
            // 获取供应商账期
            OrganizationDto vendorOrg = OrgUtils.getOrgByOrgId(vendorOrder.getOrganization_id().get(0).getId());
            String accountOrganization = vendorOrg.getTransaction_organization_id().get(0).getId();

            if (null == accountOrganization) {
                log.error("{} {} {} {} ", "save", "未查到供应商结算组织！", org, -1);
                throw new BizException("请联系平台管理员添加供应商结算组织！");
            }
            Integer vap = OrgUtils.getOrgByOrgId(accountOrganization).getStatement_cycle();

            if (null == vap) {
                log.error("{} {} {} {} ", "save", "未查到供应商结算账期！", accountOrganization, -1);

                throw new BizException("请联系平台管理员添加供应商结算账期！");
            }


            vendorOrder.setOrganization_name(vendorOrg.getName());
            vendorOrder.setAccountPeriod(vap);

            vendorOrder.setReconciliationStatus(ReconciliationStatusEnum.UNDO);
            vendorOrder.setInvoiceStatus(InvoiceStatusEnum.UNDO);
            vendorOrder.setPaymentStatus(PaymentStatusEnum.UNDO);


            //邀请供应商为空或者不包含当前供应商则为平台供应商
            vendorOrder.setPlatform(!CollectionUtils.isEmpty(vendorIds) && vendorIds.contains(vendorOrg.getId()));

            // 校验订单商品
            if (vendorOrder.getGoodsCount() < 1) throw new BizException("供应商订单商品错误!");


            //循环设置订单商品信息
            for (OrderVendorGoodsVO orderGoods : vendorOrder.getGoodsList()) {

                if (orderGoods.getQuantity().intValue() <= 0) throw new BizException("订单商品数量错误!");

                boolean isPurchase = Arrays.asList(GoodsSrcEnum.SourcingSingle, GoodsSrcEnum.SourcingLoop).contains(GoodsSrcEnum.valueOf(orderGoods.getGoods_src()));
                //客户下单 ->订单商品状态为待付款
                orderGoods.setOrder_vendor_goods_status(OrderGoodsStatusEnum.UpcomingPayment.name());
                orderGoods.setCustomer_account_period(String.valueOf(cap));
//                orderGoods.setVendorAccountPeriod(vap);
                orderGoods.setReturned_num(BigDecimal.ZERO);
                orderGoods.setReturn_received_num(BigDecimal.ZERO);

                if (null == orderGoods.getTechnical()) orderGoods.setTechnical("");
                if (null == orderGoods.getPackaging()) orderGoods.setPackaging("");
                if (null == orderGoods.getMemo()) orderGoods.setMemo("");
                if (null == orderGoods.getWarranty()) orderGoods.setWarranty("");
                if (null == orderGoods.getBar_code()) orderGoods.setBar_code("");
                if (null == orderGoods.getAttachment())
                    orderGoods.setAttachment(Collections.EMPTY_LIST);
                if (null == orderGoods.getGolden_tax()) orderGoods.setGolden_tax("");
                if (null == orderGoods.getUnspsc()) orderGoods.setUnspsc("");
                if (null == orderGoods.getDelivery()) orderGoods.setDelivery("0");

                GoodsSrcEnum goodsSrcEnum = GoodsSrcEnum.valueOf(orderGoods.getGoods_src());

                if (GoodsSrcEnum.Contract == goodsSrcEnum) {
                    //设置代购订单的初始状态
                    ifContract = true;
                    orderGoods.setOrder_vendor_goods_status(OrderGoodsStatusEnum.DoneDelivery.name());
                    customerOrder.setOrder_customer_status(OrderCustomerStatusEnum.DoneDelivery.name());
                    vendorOrder.setStatus(OrderVendorStatusEnum.DoneDelivery.name());

                } else if (GoodsSrcEnum.Shop == goodsSrcEnum) {

                    customerOrder.setType(OrderTypeEnum.ShopOrder.name());
                    //下单扣减商品库存
                    GatewayResponse<List<GoodsFullEntity>> goodsFullModelRestResponse = goodsService.pageMallGoodsByIds(Collections.singletonList(orderGoods.getGoods_id()), null);


                    if (goodsFullModelRestResponse.getData().isEmpty()) {
                        throw new BizException("商品【" + orderGoods.getName() + "】已下架，请重新选购");
                    }
                    GoodsFullEntity vse = goodsFullModelRestResponse.getData().get(0);
                    orderGoods.setDelivery(vse.getDelivery());

                    if (vse.getStock() == null) continue;
                    //todo：锁定库存
                    BigDecimal newStock = BigDecimalUtils.sub(vse.getStock(), orderGoods.getQuantity());
                    if (0 >= newStock.intValue()) {
                        throw new BizException("商品【" + orderGoods.getName() + "】库存不足");
                    }
                    Map<String, Object> updateGoodsMap = MapBuilder.create(new HashMap<String, Object>()).put("id", vse.getId()).put("stock", newStock).build();
                    boolean integerRestResponse = goodsService.updateGoods(updateGoodsMap);
                    if (integerRestResponse) {
                        throw new BizException("商品【" + orderGoods.getName() + "】库存更新失败");
                    }
                } else if (GoodsSrcEnum.EnterpriseMall == goodsSrcEnum) {
                    customerOrder.setType(OrderTypeEnum.ShopOrder.name());

                    GoodsEntity useGoods = goodsService.getGoodsById(orderGoods.getGoods_id());

                    if (null == useGoods) {
                        throw new BizException("商品【" + orderGoods.getName() + "】已下架，请重新选购");
                    }
                    orderGoods.setDelivery(useGoods.getDelivery());
                } else if (GoodsSrcEnum.ExternalMall == goodsSrcEnum) {

                } else if (isPurchase) {
                    PageImpl<GoodsPurchaseEntity> goodsPage = BoQueryUtils.Builder(ModelConst.T_GOODS_PURCHASE).condition()
                            .eq("id", orderGoods.getGoods_id())
                            .End().listBO(GoodsPurchaseEntity.class);

                    GoodsPurchaseEntity goods = goodsPage.getContent().get(0);

                    if (goodsPage.getTotal() == 0) throw new BizException("订单商品不存在!");

                    PageImpl<InquiryEntity> iePage = BoQueryUtils.Builder(ModelConst.T_INQUIRY_GOODS).condition()
                            .eq("id", goods.getInquiry_id())
                            .rpc(AppConst.SOURCING_CENTER).listBO(InquiryEntity.class);

                    if (iePage.getTotal() == 0) {
                        throw new BizException("未获取到询价单!");
                    }
                    InquiryEntity ie = iePage.getContent().get(0);

                    //循环采购不限制采购权限（子组织也能购买父组织的商品）,判断权限是否符合
                    if (!inquiryPermiss(ie, goodsSrcEnum, currentUser.getId())) {
                        throw new BizException("查看报价商品失败：询价商品不在可操作权限内");
                    }


                    if (DateUtils.strToDateDayTime(goods.getExpire()).getTime() < System.currentTimeMillis())
                        throw new BizException("商品已过期，请重新询价!");
                    PageImpl<QuotationGoodsEntity> qgPage = BoQueryUtils.Builder(ModelConst.T_QUOTATION_GOODS).condition()
                            .eq("id", goods.getQuotation_goods_id())
                            .rpc(AppConst.SOURCING_CENTER).listBO(QuotationGoodsEntity.class);

                    if (qgPage.getTotal() == 0) throw new BizException("未获取到询价商品");

                    QuotationGoodsEntity qg = qgPage.getContent().get(0);
                    //询价商品
                    PageImpl<InquiryGoodsEntity> igPage = BoQueryUtils.Builder(ModelConst.T_INQUIRY_GOODS).condition()
                            .eq("id", goods.getInquiry_goods_id())
                            .rpc(AppConst.SOURCING_CENTER).listBO(InquiryGoodsEntity.class);


                    if (igPage.getTotal() == 0) {
                        throw new BizException("未获取到询价商品!");
                    }
                    InquiryGoodsEntity ig = igPage.getContent().get(0);

                    //采购商品账期取询价单的账期
                    if (null == ie) throw new BizException("未获取到询价单!");
                    orderGoods.setCustomer_account_period(ie.getAccount_period());
                    orderGoods.setVendor_account_period(String.valueOf(vendorOrder.getAccountPeriod()));
                    orderGoods.setClient_order_vendor_goods_id(qg.getClient_vendor_goods_id());
                }
            }
        }

        //如果erpPo没值，把clientOs赋给它
        if (!RegexUtils.notNull(customerOrder.getErp_po()) && !RegexUtils.notNull(customerOrder.getExtends_attr())) {
            Map<String, Object> jsonObject = JSON.parseObject(customerOrder.getExtends_attr());

            customerOrder.setErp_po(Objects.toString(jsonObject.get("clientOs"), ""));
        }

        // 保存新建订单
        customerOrder = save(customerOrder);


        //todo 生成转采订单
        creatTransferOrder(customerOrder);

        //todo 消息推送,流程审批,数据推送


        return customerOrder;
    }

    private boolean inquiryPermiss(InquiryEntity ie, GoodsSrcEnum src, String memberId) {
        if (src == GoodsSrcEnum.SourcingSingle) {
            String inquiryMemberId = ie.getMember_id().get(0).getId();
            List<String> inquiryMemberIdList = UserUtils.listSubMemberIds(memberId);

            if (!CollectionUtils.isEmpty(inquiryMemberIdList) && !inquiryMemberIdList.contains(inquiryMemberId)) {
                return false;
            }

        }
        return true;
    }

    private OrderCustomerVO save(OrderCustomerVO orderCustomerVO) {

        //客户订单
        OrderCustomerEntity customerEntity = new OrderCustomerEntity();
        //供应商订单
        List<OrderVendorEntity> vendorList = new ArrayList<>();
        //供应商订单商品
        List<OrderVendorGoodsEntity> vendorGoodsList = new ArrayList<>();
        //客户订单商品
        List<OrderCustomerGoodsEntity> customerGoodsList = new ArrayList<>();

        //订单关系表
        List<OrderGoodsRelationEntity> relationList = new ArrayList<>();

        //客户订单赋值并生成id
        BeanUtils.copyProperties(orderCustomerVO, customerEntity);
        customerEntity.setId(SchemaHelper.getId());

        for (OrderVendorVO vendorVO : orderCustomerVO.getOrderVendorVO()) {
            //生成id,并保存客户订单id
            vendorVO.setId(SchemaHelper.getId());
            vendorVO.setOrder_customer_id(customerEntity.getId());

            //供应商订单,
            OrderVendorEntity vendorEntity = new OrderVendorEntity();
            BeanUtils.copyProperties(vendorVO, vendorEntity);
            vendorList.add(vendorEntity);

            for (OrderVendorGoodsVO vendorGoodsVO : vendorVO.getGoodsList()) {

                //生成id,并保存客户订单id
                vendorGoodsVO.setId(SchemaHelper.getId());
                vendorGoodsVO.setOrder_vendor_id(vendorVO.getId());
                vendorGoodsVO.setOrder_customer_id(vendorVO.getOrder_customer_id());

                //订单商品关系表
                OrderGoodsRelationEntity relationEntity = vendorGoodsVO.getOrderGoodsRelationEntity();
                if (relationEntity != null) {
                    relationEntity.setId(SchemaHelper.getId());
                    vendorGoodsVO.setRelation_id(relationEntity.getId());
                    relationList.add(relationEntity);
                }

                //供应商订单商品
                OrderVendorGoodsEntity vendorGoodsEntity = new OrderVendorGoodsEntity();
                BeanUtils.copyProperties(vendorGoodsVO, vendorGoodsEntity);
                vendorGoodsList.add(vendorGoodsEntity);

                //客户订单商品
                OrderCustomerGoodsEntity customerGoodsEntity = new OrderCustomerGoodsEntity();
                BeanUtils.copyProperties(vendorGoodsVO, customerGoodsEntity);
                customerGoodsEntity.setId(SchemaHelper.getId());
            }

        }

        //保存

        if (CollectionUtils.isEmpty(vendorList) ||
                CollectionUtils.isEmpty(vendorGoodsList) ||
                ObjectUtils.isEmpty(customerEntity) ||
                CollectionUtils.isEmpty(customerGoodsList)
        ) {
            throw new BizException("保存失败,订单数据为空");
        }

        List<HttpClientBO> creatList = new ArrayList<>();
        creatList.add(new HttpClientBO(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER, Arrays.asList(customerEntity)));
        creatList.add(new HttpClientBO(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR, vendorList));
        creatList.add(new HttpClientBO(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS, customerGoodsList));
        creatList.add(new HttpClientBO(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR_GOODS, vendorGoodsList));

        if (!relationList.isEmpty()) {
            creatList.add(new HttpClientBO(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION, relationList));
        }
        SingleResponse<BO> bo;
        for (HttpClientBO clientBO : creatList) {
            bo = HttpClients.createBO(clientBO.appCode(), clientBO.schemaCode(), clientBO.data());
            if (!bo.isSuccess()) {
                log.error("订单创建失败:appCode={},schemaCode={},错误={}", bo.getErrMessage());
                throw new BizException("保存失败:" + bo.getErrMessage());
            }
        }

        return orderCustomerVO;
    }

    /**
     * 生成转彩
     *
     * @param customerOrder
     */
    public void creatTransferOrder(OrderCustomerVO customerOrder) {


    }

    /**
     * 校验客户订单数据
     *
     * @param customerOrder
     */
    private void checkOrder(OrderCustomerVO customerOrder) {

        if (null == customerOrder) {
            throw new BizException("客户订单数据错误!");
        }
        if (customerOrder.getVendorCount() < 1) {
            throw new BizException("供应商订单数据错误!");
        }

        if (null == customerOrder.getAddress() || !StringUtils.between(customerOrder.getAddress(), 0, 500)) {
            throw new BizException("客户订单地址为空!");
        }
        if (null == customerOrder.getPhone() || !StringUtils.between(customerOrder.getPhone(), 0, 50)) {
            throw new BizException("客户订单电话为空!");
        }
        if (null == customerOrder.getReceiver() || !StringUtils.between(customerOrder.getReceiver(), 0, 50)) {
            throw new BizException("收货人为空!");
        }
        if (null == customerOrder.getPostal()) {
            customerOrder.setPostal("");
        }
        if (null == customerOrder.getErp_po()) {
            customerOrder.setErp_po("");
        }
        if (null == customerOrder.getClient_id()) {
            customerOrder.setClient_id("");
        }

        if (null == customerOrder.getClient_user_id()) {
            customerOrder.setClient_user_id("");
        }

        if (null == customerOrder.getClient_order_id()) {
            customerOrder.setClient_order_id("");
        }

    }

    private List<MemberDeliverAddressEntity> listMemberDeliverAddressByMember(String memberId, boolean defaultOnly, String id) {

        return JdbcTemplateUtils.builder(AppConst.PERSONAL_CENTER, ModelConst.T_MEMBER_DELIVER_ADDRESS)
                .selectField(" * ")
                .eq("id", id)
                .eq("default_address", true)
                .eq("member_Id -> '$.id'", memberId)
                .queryForJavaBean(MemberDeliverAddressEntity.class);
    }

    private static class OrderServiceImplBuilder {
        private static final OrderServiceImpl instance = new OrderServiceImpl();
    }


}
